(function($,win){
	win.JSON = {};

	var rx_one = /^[\],:{}\s]*$/;
	var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
	var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
	var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
	var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
	var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

	function f(n) {
		return n < 10
			? "0" + n
			: n;
	}

	function this_value() {
		return this.valueOf();
	}

	if (typeof Date.prototype.toJSON !== "function") {

		Date.prototype.toJSON = function () {

			return isFinite(this.valueOf())
				? this.getUTCFullYear() + "-" +
						f(this.getUTCMonth() + 1) + "-" +
						f(this.getUTCDate()) + "T" +
						f(this.getUTCHours()) + ":" +
						f(this.getUTCMinutes()) + ":" +
						f(this.getUTCSeconds()) + "Z"
				: null;
		};

		Boolean.prototype.toJSON = this_value;
		Number.prototype.toJSON = this_value;
		String.prototype.toJSON = this_value;
	}

	var gap;
	var indent;
	var meta;
	var rep;


	function quote(string) {

		rx_escapable.lastIndex = 0;
		return rx_escapable.test(string)
			? "\"" + string.replace(rx_escapable, function (a) {
				var c = meta[a];
				return typeof c === "string"
					? c
					: "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
			}) + "\""
			: "\"" + string + "\"";
	}


	function str(key, holder) {

		var i;          // The loop counter.
		var k;          // The member key.
		var v;          // The member value.
		var length;
		var mind = gap;
		var partial;
		var value = holder[key];

		if (value && typeof value === "object" &&
				typeof value.toJSON === "function") {
			value = value.toJSON(key);
		}
		if (typeof rep === "function") {
			value = rep.call(holder, key, value);
		}
		switch (typeof value) {
		case "string":
			return quote(value);

		case "number":
			return isFinite(value)
				? String(value)
				: "null";

		case "boolean":
		case "null":
			return String(value);
		case "object":

			if (!value) {
				return "null";
			}

			gap += indent;
			partial = [];

			if (Object.prototype.toString.apply(value) === "[object Array]") {

				length = value.length;
				for (i = 0; i < length; i += 1) {
					partial[i] = str(i, value) || "null";
				}

				v = partial.length === 0
					? "[]"
					: gap
						? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
						: "[" + partial.join(",") + "]";
				gap = mind;
				return v;
			}

			if (rep && typeof rep === "object") {
				length = rep.length;
				for (i = 0; i < length; i += 1) {
					if (typeof rep[i] === "string") {
						k = rep[i];
						v = str(k, value);
						if (v) {
							partial.push(quote(k) + (
								gap
									? ": "
									: ":"
							) + v);
						}
					}
				}
			} else {

				for (k in value) {
					if (Object.prototype.hasOwnProperty.call(value, k)) {
						v = str(k, value);
						if (v) {
							partial.push(quote(k) + (
								gap
									? ": "
									: ":"
							) + v);
						}
					}
				}
			}

			v = partial.length === 0
				? "{}"
				: gap
					? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
					: "{" + partial.join(",") + "}";
			gap = mind;
			return v;
		}
	}

	if (typeof JSON.stringify !== "function") {
		meta = {    // table of character substitutions
			"\b": "\\b",
			"\t": "\\t",
			"\n": "\\n",
			"\f": "\\f",
			"\r": "\\r",
			"\"": "\\\"",
			"\\": "\\\\"
		};
		JSON.stringify = function (value, replacer, space) {

			var i;
			gap = "";
			indent = "";

			if (typeof space === "number") {
				for (i = 0; i < space; i += 1) {
					indent += " ";
				}

			} else if (typeof space === "string") {
				indent = space;
			}

			rep = replacer;
			if (replacer && typeof replacer !== "function" &&
					(typeof replacer !== "object" ||
					typeof replacer.length !== "number")) {
				throw new Error("JSON.stringify");
			}

			return str("", {"": value});
		};
	}

	if (typeof JSON.parse !== "function") {
		JSON.parse = function (text, reviver) {

			var j;

			function walk(holder, key) {

				var k;
				var v;
				var value = holder[key];
				if (value && typeof value === "object") {
					for (k in value) {
						if (Object.prototype.hasOwnProperty.call(value, k)) {
							v = walk(value, k);
							if (v !== undefined) {
								value[k] = v;
							} else {
								delete value[k];
							}
						}
					}
				}
				return reviver.call(holder, key, value);
			}

			text = String(text);
			rx_dangerous.lastIndex = 0;
			if (rx_dangerous.test(text)) {
				text = text.replace(rx_dangerous, function (a) {
					return "\\u" +
							("0000" + a.charCodeAt(0).toString(16)).slice(-4);
				});
			}

			if (
				rx_one.test(
					text
						.replace(rx_two, "@")
						.replace(rx_three, "]")
						.replace(rx_four, "")
				)
			) {

				j = eval("(" + text + ")");

				return (typeof reviver === "function")
					? walk({"": j}, "")
					: j;
			}

			throw new SyntaxError("JSON.parse");
		};
	}
	
	win.extend = function(sub, sup){
		function Fun(){}
		Fun.prototype = sup.prototype;
		sub.prototype = new Fun();
		sub.prototype.constructor = sub;
	};
	win.JLayout = function(){
		//all object type
		this.stop = false;
		this.useTime = 0;
	};
	JLayout.copy = function(obj, ext){
		if(ext && typeof ext === "object"){
			for(var i in ext){
				obj[i] = ext[i];
			}
		}
		return obj;
	};
	JLayout.colorHex = function(str){
		var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
		var that = str;
		if(/^(rgb|RGB)/.test(that)){
			var aColor = that.replace(/(?:\(|\)|rgb|RGB)*/g,"").split(",");
			var strHex = "";
			for(var i=0; i<aColor.length; i++){
			   var hex = Number(aColor[i]).toString(16);
			   if(hex === "0"){
					hex += hex;    
			   }
			   strHex += hex;
			}
			if(strHex.length !== 6){
			   strHex = that;    
			}
			return strHex;
		}else if(reg.test(that)){
			var strNum = that.replace(/#/,"");
			var aNum = strNum.split("");
			if(aNum.length === 6){
			   return strNum;    
			}else if(aNum.length === 3){
			   var numHex = "";
			   for(var i=0; i<aNum.length; i+=1){
					numHex += (aNum[i]+aNum[i]);
			   }
			   return numHex;
			}
		}else{
		  return that;    
		}
	};
	JLayout.ajax = function(opt){
		var origin = {
			type: "POST",
			dataType: "json",//xml,html,script,json,jsonp,text
		};
		JLayout.copy(origin, opt);
		$.ajax(origin);
	};
	JLayout.cookie = function (key, value, options) {
		var pluses = /\+/g;

		var config = {};
		
		function encode(s) {
			return config.raw ? s : encodeURIComponent(s);
		}

		function decode(s) {
			return config.raw ? s : decodeURIComponent(s);
		}

		function stringifyCookieValue(value) {
			return encode(config.json ? JSON.stringify(value) : String(value));
		}

		function parseCookieValue(s) {
			if (s.indexOf('"') === 0) {
				// This is a quoted cookie as according to RFC2068, unescape...
				s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
			}

			try {
				// Replace server-side written pluses with spaces.
				// If we can't decode the cookie, ignore it, it's unusable.
				// If we can't parse the cookie, ignore it, it's unusable.
				s = decodeURIComponent(s.replace(pluses, ' '));
				return config.json ? JSON.parse(s) : s;
			} catch(e) {}
		}

		function read(s, converter) {
			var value = config.raw ? s : parseCookieValue(s);
			return $.isFunction(converter) ? converter(value) : value;
		}
		

		options = $.extend(config, options);
		// Write
		if (value !== undefined && !$.isFunction(value)) {

			if (typeof options.expires === 'number') {
				var days = options.expires, t = options.expires = new Date();
				t.setTime(+t + days * 864e+5);
			}
			return (document.cookie = [
				encode(key), '=', stringifyCookieValue(value),
				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
				options.path    ? '; path=' + options.path : '',
				options.domain  ? '; domain=' + options.domain : '',
				options.secure  ? '; secure' : ''
			].join(''));
		}

		// Read
		var result = key ? undefined : {};

		// To prevent the for loop in the first place assign an empty array
		// in case there are no cookies at all. Also prevents odd result when
		// calling $.cookie().
		var cookies = document.cookie ? document.cookie.split('; ') : [];

		for (var i = 0, l = cookies.length; i < l; i++) {
			var parts = cookies[i].split('=');
			var name = decode(parts.shift());
			var cookie = parts.join('=');

			if (key && key === name) {
				// If second argument (value) is a function it's a converter...
				result = read(cookie, value);
				break;
			}

			// Prevent storing a cookie that we couldn't decode.
			if (!key && (cookie = read(cookie)) !== undefined) {
				result[name] = cookie;
			}
		}

		return result;
	};
	JLayout.easing = {
		linear: function(t, b, c, d) {
			return c*t/d + b;
		},
		swing: function(t, b, c, d) {
			return c*(0.5 - Math.cos( t/d*Math.PI ) / 2) + b;
		},
		easeInQuad: function (t, b, c, d) {
				return c*(t/=d)*t + b;
		},
		easeOutQuad: function (t, b, c, d) {
				return -c *(t/=d)*(t-2) + b;
		},
		easeInOutQuad: function (t, b, c, d) {
				if ((t/=d/2) < 1) return c/2*t*t + b;
				return -c/2 * ((--t)*(t-2) - 1) + b;
		},
		easeInCubic: function (t, b, c, d) {
				return c*(t/=d)*t*t + b;
		},
		easeOutCubic: function (t, b, c, d) {
				return c*((t=t/d-1)*t*t + 1) + b;
		},
		easeInOutCubic: function (t, b, c, d) {
				if ((t/=d/2) < 1) return c/2*t*t*t + b;
				return c/2*((t-=2)*t*t + 2) + b;
		},
		easeInQuart: function (t, b, c, d) {
				return c*(t/=d)*t*t*t + b;
		},
		easeOutQuart: function (t, b, c, d) {
				return -c * ((t=t/d-1)*t*t*t - 1) + b;
		},
		easeInOutQuart: function (t, b, c, d) {
				if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
				return -c/2 * ((t-=2)*t*t*t - 2) + b;
		},
		easeInQuint: function (t, b, c, d) {
				return c*(t/=d)*t*t*t*t + b;
		},
		easeOutQuint: function (t, b, c, d) {
				return c*((t=t/d-1)*t*t*t*t + 1) + b;
		},
		easeInOutQuint: function (t, b, c, d) {
				if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
				return c/2*((t-=2)*t*t*t*t + 2) + b;
		},
		easeInSine: function (t, b, c, d) {
				return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
		},
		easeOutSine: function (t, b, c, d) {
				return c * Math.sin(t/d * (Math.PI/2)) + b;
		},
		easeInOutSine: function (t, b, c, d) {
				return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
		},
		easeInExpo: function (t, b, c, d) {
				return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
		},
		easeOutExpo: function (t, b, c, d) {
				return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
		},
		easeInOutExpo: function (t, b, c, d) {
				if (t==0) return b;
				if (t==d) return b+c;
				if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
				return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
		},
		easeInCirc: function (t, b, c, d) {
				return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
		},
		easeOutCirc: function (t, b, c, d) {
				return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
		},
		easeInOutCirc: function (t, b, c, d) {
				if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
				return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
		},
		easeInElastic: function (t, b, c, d) {
				var s=1.70158;var p=0;var a=c;
				if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
				if (a < Math.abs(c)) { a=c; var s=p/4; }
				else var s = p/(2*Math.PI) * Math.asin (c/a);
				return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		},
		easeOutElastic: function (t, b, c, d) {
				var s=1.70158;var p=0;var a=c;
				if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
				if (a < Math.abs(c)) { a=c; var s=p/4; }
				else var s = p/(2*Math.PI) * Math.asin (c/a);
				return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
		},
		easeInOutElastic: function (t, b, c, d) {
				var s=1.70158;var p=0;var a=c;
				if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
				if (a < Math.abs(c)) { a=c; var s=p/4; }
				else var s = p/(2*Math.PI) * Math.asin (c/a);
				if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
				return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
		},
		easeInBack: function (t, b, c, d, s) {
				if (s == undefined) s = 1.70158;
				return c*(t/=d)*t*((s+1)*t - s) + b;
		},
		easeOutBack: function (t, b, c, d, s) {
				if (s == undefined) s = 1.70158;
				return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
		},
		easeInOutBack: function (t, b, c, d, s) {
				if (s == undefined) s = 1.70158; 
				if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
				return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
		},
		easeInBounce: function (t, b, c, d) {
				return c - JLayout.easing.easeOutBounce (d-t, 0, c, d) + b;
		},
		easeOutBounce: function (t, b, c, d) {
				if ((t/=d) < (1/2.75)) {
						return c*(7.5625*t*t) + b;
				} else if (t < (2/2.75)) {
						return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
				} else if (t < (2.5/2.75)) {
						return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
				} else {
						return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
				}
		},
		easeInOutBounce: function (t, b, c, d) {
				if (t < d/2) return JLayout.easing.easeInBounce (t*2, 0, c, d) * .5 + b;
				return JLayout.easing.easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
		}
	};
	JLayout.prototype = {
		constructor : JLayout,
		getEngine : function(){
			return $;
		},
		getScreenWidth : function(){
			return getEngine()(window).width();
		},
		getScreenHeight : function(){
			return getEngine()(window).height();
		},
		animation : function(opt){
			var timeGap = 1000 / opt.fps;
			var engine = this.getEngine();
			if(engine.isArray(opt.easing)){
				var size = opt.easing.length;
				for(var i = 0; i < size; i++){
					var from = engine.isArray(opt.from) ? opt.from[i] : opt.from;
					var to = engine.isArray(opt.to) ? opt.to[i] : opt.to;
					var n = opt.easing[i](this.useTime, from, to - from, opt.duration);
					if(n > to){
						n = to;
					}
					opt.onRepeat && opt.onRepeat(n, i);
				}
				if(!this.stop && this.useTime < opt.duration){
					var thiz = this;
					setTimeout(function(){
						thiz.animation(opt);
					}, timeGap);
				}else{
					opt.onStop && opt.onStop();
				}
				this.useTime += timeGap;
			}else{
				var n = opt.easing(this.useTime, opt.from, opt.to - opt.from, opt.duration);
				if(n > opt.to){
					n = opt.to;
				}
				opt.onRepeat && opt.onRepeat(n);
				if(!this.stop && this.useTime < opt.duration){
					var thiz = this;
					setTimeout(function(){
						thiz.animation(opt);
					}, timeGap);
				}else{
					opt.onStop && opt.onStop();
				}
				this.useTime += timeGap;
			}
		},
		startAnimation : function(opt){
			opt = JLayout.copy({
				easing : JLayout.easing.easeOutQuint,
				onStart : function(){},
				onStop : function(){},
				onRepeat : function(n, type){},
				fps : 60,
				duration : 1000,
				from : 0,
				to : 1
			}, opt);
			this.stop = false;
			this.useTime = 0;
			opt.onStart && opt.onStart();
			this.animation(opt);
		},
		stopAnimation : function(){
			this.stop = true;
		}
	};
	
	win.Panel = function(selector){
		//html normal element
		JLayout.call(this);
		this.setCore(selector);
	};extend(Panel, JLayout);
	Panel.prototype.getCore = function(){
		return this.core;
	};
	Panel.prototype.setCore = function(core){
		if(core instanceof JLayout){
			this.core = core.getCore();
		}else if(core instanceof this.getEngine()){
			this.core = core;
		}else{
			this.core = this.getEngine()(core);
		}
	};
	Panel.prototype.html = function(arg){
		var core = this.getCore();
		return arg ? core.html(arg) : core.html();
	};
	Panel.prototype.width = function(arg){
		var core = this.getCore();
		return arg ? core.width(arg) : core.width();
	};
	Panel.prototype.height = function(arg){
		var core = this.getCore();
		return arg ? core.height(arg) : core.height();
	};
	Panel.prototype.margin = function(dire, arg){
		var core = this.getCore();
		return arg ? core.css("margin-"+dire, arg+"px") : parseInt(core.css("margin-"+dire));
	};
	Panel.prototype.padding = function(dire, arg){
		var core = this.getCore();
		return arg ? core.css("padding-"+dire, arg+"px") : parseInt(core.css("padding-"+dire));
	};
	Panel.prototype.left = function(arg){
		var core = this.getCore();
		return arg ? core.css("left", arg+"px") : parseInt(core.css("left"));
	};
	Panel.prototype.top = function(arg){
		var core = this.getCore();
		return arg ? core.css("top", arg+"px") : parseInt(core.css("top"));
	};
	Panel.prototype.radius = function(arg){
		var core = this.getCore();
		return arg ? core.css("border-radius", arg+"px") : parseInt(core.css("border-radius"));
	};
	Panel.prototype.borderWidth = function(arg){
		var core = this.getCore();
		return arg ? core.css("border-width", arg+"px") : parseInt(core.css("border-width"));
	};
	Panel.prototype.borderColor = function(arg){
		var core = this.getCore();
		if(arg && this.getEngine().isNumeric(arg)){
			var color = arg.toString(16);
			var N = 6 - color.length;
			if(N > 0){
				for(var i = 0; i < N; i++){
					color = "0" + color;
				}
			}
			return core.css("border-color", "#"+color);
		}
		return parseInt(JLayout.colorHex(core.css("border-color")), 16);
	};
	Panel.prototype.borderStyle = function(arg){
		var core = this.getCore();
		return arg ? core.css("border-style", arg) : core.css("border-style");
	};
	Panel.prototype.background = function(arg){
		var core = this.getCore();
		return arg ? core.css("background", arg) : core.css("background");
	};
	Panel.prototype.position = function(arg){
		var core = this.getCore();
		return arg ? core.css("position", arg) : parseInt(core.css("position"));
	};
	Panel.prototype.display = function(arg){
		var core = this.getCore();
		return arg ? core.css("display", arg) : parseInt(core.css("display"));
	};
	Panel.prototype.drift = function(arg){
		var core = this.getCore();
		return arg ? core.css("float", arg) : parseInt(core.css("float"));
	};
	Panel.prototype.lineHeight = function(arg){
		var core = this.getCore();
		return arg ? core.css("line-height", arg+"px") : parseInt(core.css("top"));
	};
	Panel.prototype.textSize = function(arg){
		var core = this.getCore();
		return arg ? core.css("fint-size", arg+"px") : parseInt(core.css("top"));
	};
	Panel.prototype.color = function(arg){
		var core = this.getCore();
		if(arg && this.getEngine().isNumeric(arg)){
			var color = arg.toString(16);
			var N = 6 - color.length;
			if(N > 0){
				for(var i = 0; i < N; i++){
					color = "0" + color;
				}
			}
			return core.css("color", "#"+color);
		}
		return parseInt(JLayout.colorHex(core.css("color")), 16);
	};
	Panel.prototype.show = function(arg){
		var core = this.getCore();
		if(arg){
			core.show();
		}else{
			core.hide();
		}
	};
	Panel.prototype.each = function(arg){
		var core = this.getCore();
		core.each(function(){
			var thiz = new Panel(this);
			arg(arguments[0], thiz);
		});
	};
	Panel.prototype.find = function(arg){
		var core = this.getCore();
		return core.find(arg);
	};
	Panel.prototype.children = function(arg){
		var core = this.getCore();
		return arg ? core.children(arg) : core.children();
	};
	Panel.prototype.siblings = function(arg){
		var core = this.getCore();
		return arg ? core.siblings(arg) : core.siblings();
	};
	Panel.prototype.filter = function(arg){
		var core = this.getCore();
		return core.filter(arg);
	};
	Panel.prototype.attr = function(name, value){
		var core = this.getCore();
		return value ? core.attr(arg, value) : core.attr(name);
	};
	Panel.prototype.on = function(evn, fun){
		var core = this.getCore();
		core.on(evn, fun);
	};
	
	win.Form = function(selector){
		//html normal element
		Panel.call(this, selector);
	};extend(Form, Panel);
	Form.prototype.serialize = function(){
		//name=value&name=value...
		var core = this.getCore();
		return core.serialize();
	};
	Form.prototype.serializeArray = function(){
		//[{name:"", value:""},{name:"", value:""},...]
		var core = this.getCore();
		return core.serializeArray();
	};
	Form.prototype.serializeObject = function(){
		//[{name:"", value:""},{name:"", value:""},...]
		var core = this.getCore();
		var array = core.serializeArray();
		var ret = {};
		for(var i = 0; i < array.length; i++){
			var name = array[i].name;
			var value = array[i].value;
			ret[name] = value;
		}
		return ret;
	};
	Form.prototype.val = function(value){
		var core = this.getCore();
		return value ? core.val(value) : core.val();
	};
	Form.prototype.sumbit = function(value){
		var core = this.getCore();
		return value ? core.val(value) : core.val();
	};
	
})(jQuery, window);